{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b8465167",
   "metadata": {},
   "source": [
    "# Adding new backends\n",
    "\n",
    "This notebook displays how to integrate a new plotting backend to `sisl.viz`.\n",
    "\n",
    "Let's create a toy graphene band structure to illustrate the conceps throughout this notebook:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "392448ab",
   "metadata": {},
   "outputs": [],
   "source": [
    "import sisl\n",
    "\n",
    "geom = sisl.geom.graphene(orthogonal=True)\n",
    "H = sisl.Hamiltonian(geom)\n",
    "H.construct(\n",
    "    [(0.1, 1.44), (0, -2.7)],\n",
    ")\n",
    "\n",
    "band_struct = sisl.BandStructure(H, [[0, 0, 0], [0.5, 0, 0]], 10, [\"Gamma\", \"X\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df72db95",
   "metadata": {},
   "source": [
    "The final display in the visualization module is controlled by the `Figure` class."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "739c2e2f-ef7f-48dc-a757-10a92be82f4e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sisl.viz import Figure"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11089ee9-431f-484d-8b83-ceddd5b0b00d",
   "metadata": {},
   "source": [
    "And backends are stored in `sisl.viz.figure.BACKENDS`. It is just a dictionary containing extensions of the `Figure` class for particular plotting frameworks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c16cebe2-faec-491b-89b8-12ef74d6c504",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sisl.viz.figure import BACKENDS\n",
    "\n",
    "BACKENDS"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe8e1f24-a3f6-4b01-b980-7d4dce7cb74f",
   "metadata": {},
   "source": [
    "Therefore, to add a new backend we must follow two steps:\n",
    "1. **Subclass `Figure`**, adding backend specific functionality.\n",
    "2. **Register** the backend.\n",
    "\n",
    "The documentation of the `Figure` class explains what you should do to extend it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ae3dcf66-fd10-47bb-a706-b24b4bb2ba40",
   "metadata": {},
   "outputs": [],
   "source": [
    "help(Figure)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33aabd81-749e-468f-9f3b-fd19cf8704aa",
   "metadata": {},
   "source": [
    "Therefore, we need to implement some of the methods of the `Figure` class. The more we implement, the more we will support `sisl.viz`.\n",
    "\n",
    "Here's an example of a very simple backend that just writes text:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b61046a2-d4a9-4e49-b1a7-3fbf11d2eee7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "\n",
    "class TextFigure(Figure):\n",
    "    def _init_figure(self, *args, **kwargs):\n",
    "        self.text = \"\"\n",
    "\n",
    "    def clear(self):\n",
    "        self.text = \"\"\n",
    "\n",
    "    def draw_line(self, x, y, name, **kwargs):\n",
    "        self.text += f\"\\nLINE: {name}\\n{np.array(x)}\\n{np.array(y)}\"\n",
    "\n",
    "    def draw_scatter(self, x, y, name, **kwargs):\n",
    "        self.text += f\"\\nSCATTER: {name}\\n{np.array(x)}\\n{np.array(y)}\"\n",
    "\n",
    "    def show(self):\n",
    "        print(self.text)\n",
    "\n",
    "    def _ipython_display_(self):\n",
    "        self.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "946c792e-5152-4d09-a5eb-2ff5d1f2e422",
   "metadata": {},
   "source": [
    "And all that is left now is to register the backend by simply adding it to the `BACKENDS` dictionary."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d1986892-98c0-4b9c-b8fe-735f00de30c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "BACKENDS[\"text\"] = TextFigure"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a7054c9-06ba-467a-9b40-f83a3612160d",
   "metadata": {},
   "source": [
    "Let's plot the bands to check that it works."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0af709ce-2b96-4a45-8264-7dcc87968b26",
   "metadata": {},
   "outputs": [],
   "source": [
    "plot = band_struct.plot()\n",
    "plot"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c9ffe0d9-6ee8-4a61-996d-f30bd2ef2391",
   "metadata": {},
   "source": [
    "The default backend has been used, let's now change it to our new `\"text\"` backend."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "df588bab-8bd0-4dd0-b7e8-9c354dcb4b65",
   "metadata": {},
   "outputs": [],
   "source": [
    "plot.update_inputs(backend=\"text\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f2397d3",
   "metadata": {},
   "source": [
    "Not a very visually appealing backend, but it serves the purpose of demonstrating how it is done. Now it is your turn!\n",
    "\n",
    "<div class=\"alert alert-info\">\n",
    "    \n",
    "Note\n",
    "    \n",
    "For a complex framework you might take inspiration from the already implemented backends in `sisl.viz.figure.*`.\n",
    "    \n",
    "</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "543c11eb-c0ed-43bf-88bb-df1b7d7e982d",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
